local options = {}
local f = CreateFrame("frame")

local config = CreateFrame("Frame")
local configOpenRunOnce = false

local function printFormattedString(t, sid, sn, ss, ssid)
	local msg = options.message
	msg = msg:gsub("%%t", t):gsub("%%sn", sn):gsub("%%sc", CombatLog_String_SchoolString(ss)):gsub("%%sl", GetSpellLink(sid)):gsub("%%ys", GetSpellLink(ssid))
	if options.channel == "SELF" then
		print(msg)
	else
		local ec = options.channelExtra
		local announceChannel = options.channel
		if options.channel == "CHANNEL" and options.channelExtra then
			ec = GetChannelName(options.channelExtra)
		end

		if not IsInGroup(2) then
			if IsInRaid() then
				if announceChannel == "INSTANCE_CHAT" then announceChannel = "RAID" end
			elseif IsInGroup(1) then
				if announceChannel == "INSTANCE_CHAT" then announceChannel = "PARTY" end
			end	
		elseif IsInGroup(2) then
			if announceChannel == "RAID" then announceChannel = "INSTANCE_CHAT" end
			if announceChannel == "PARTY" then announceChannel = "INSTANCE_CHAT" end
		end
			
		SendChatMessage(msg, announceChannel, nil, ec)
	end
end

local function registerEvents()
	if options.enabled then
		local inInstance, instanceType = IsInInstance()
		if instanceType == "arena" and options.inArena then
			f:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
		elseif instanceType == "party" and options.inParty then
			f:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
		elseif instanceType == "pvp" and options.inBG then
			f:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
		elseif instanceType == "raid" and options.inRaid then
			f:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
		elseif instanceType == "none" and options.outdoors then
			f:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
		elseif instanceType == "scenario" and options.inScenario then
			f:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
		else
			f:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
		end
	else
		f:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
	end
end

local function selectIdFromChannelName(cname)
	if cname == "SAY" then
		return 1
	elseif cname == "RAID" then
		return 2
	elseif cname == "PARTY" then
		return 3
	elseif cname == "INSTANCE_CHAT" then
		return 4
	elseif cname == "YELL" then
		return 5
	elseif cname == "SELF" then
		return 6
	elseif cname == "WHISPER" then
		return 7
	elseif cname == "CHANNEL" then
		return 8
	end
	return 1
end

local function getBoolean(val)
	if val then
		return true
	else
		return false
	end
end

function showAIConfig(c)
	if configOpenRunOnce then
		return
	end

	configOpenRunOnce = true

	config.title = config:CreateFontString("AIconfigTitleFont", "ARTWORK", "GameFontNormal")
	config.title:SetFont(GameFontNormal:GetFont(), 16, "OUTLINE")
	config.title:SetPoint("TOPLEFT", config, 10, -10)
	config.title:SetText(config.name)

	config.enablebox = CreateFrame("CheckButton", "AIenableButton", config, "InterfaceOptionsCheckButtonTemplate")
	config.enablebox:SetPoint("TOPLEFT", config, 10, -28)
	config.enablebox:SetChecked(options.enabled)
	config.enableboxtitle = config:CreateFontString("AIconfigEnableboxFont", "ARTWORK", "GameFontNormal")
	config.enableboxtitle:SetFont(GameFontNormal:GetFont(), 12, "OUTLINE")
	config.enableboxtitle:SetPoint("LEFT", config.enablebox, 30, 0)
	config.enableboxtitle:SetText("|cffffffffEnable addon|r")


	config.raidbox = CreateFrame("CheckButton", "AIraidButton", config, "InterfaceOptionsCheckButtonTemplate")
	config.raidbox:SetPoint("TOPLEFT", config, 10, -68)
	config.raidbox:SetChecked(options.inRaid)
	config.raidboxtitle = config:CreateFontString("AIconfigraidboxFont", "ARTWORK", "GameFontNormal")
	config.raidboxtitle:SetFont(GameFontNormal:GetFont(), 12, "OUTLINE")
	config.raidboxtitle:SetPoint("LEFT", config.raidbox, 30, 0)
	config.raidboxtitle:SetText("|cffffffffActive in raid instances|r")

	config.partybox = CreateFrame("CheckButton", "AIpartyButton", config, "InterfaceOptionsCheckButtonTemplate")
	config.partybox:SetPoint("TOPLEFT", config, 10, -88)
	config.partybox:SetChecked(options.inParty)
	config.partyboxtitle = config:CreateFontString("AIconfigpartyboxFont", "ARTWORK", "GameFontNormal")
	config.partyboxtitle:SetFont(GameFontNormal:GetFont(), 12, "OUTLINE")
	config.partyboxtitle:SetPoint("LEFT", config.partybox, 30, 0)
	config.partyboxtitle:SetText("|cffffffffActive in 5-man instances|r")

	config.bgbox = CreateFrame("CheckButton", "AIbgButton", config, "InterfaceOptionsCheckButtonTemplate")
	config.bgbox:SetPoint("TOPLEFT", config, 10, -108)
	config.bgbox:SetChecked(options.inBG)
	config.bgboxtitle = config:CreateFontString("AIconfigbgboxFont", "ARTWORK", "GameFontNormal")
	config.bgboxtitle:SetFont(GameFontNormal:GetFont(), 12, "OUTLINE")
	config.bgboxtitle:SetPoint("LEFT", config.bgbox, 30, 0)
	config.bgboxtitle:SetText("|cffffffffActive in battlegrounds|r")

	config.arenabox = CreateFrame("CheckButton", "AIarenaButton", config, "InterfaceOptionsCheckButtonTemplate")
	config.arenabox:SetPoint("TOPLEFT", config, 10, -128)
	config.arenabox:SetChecked(options.inArena)
	config.arenaboxtitle = config:CreateFontString("AIconfigarenaboxFont", "ARTWORK", "GameFontNormal")
	config.arenaboxtitle:SetFont(GameFontNormal:GetFont(), 12, "OUTLINE")
	config.arenaboxtitle:SetPoint("LEFT", config.arenabox, 30, 0)
	config.arenaboxtitle:SetText("|cffffffffActive in arenas|r")

	config.scenariobox = CreateFrame("CheckButton", "AIscenarioButton", config, "InterfaceOptionsCheckButtonTemplate")
	config.scenariobox:SetPoint("TOPLEFT", config, 10, -148)
	config.scenariobox:SetChecked(options.inScenario)
	config.scenarioboxtitle = config:CreateFontString("AIconfigscenarioboxFont", "ARTWORK", "GameFontNormal")
	config.scenarioboxtitle:SetFont(GameFontNormal:GetFont(), 12, "OUTLINE")
	config.scenarioboxtitle:SetPoint("LEFT", config.scenariobox, 30, 0)
	config.scenarioboxtitle:SetText("|cffffffffActive in scenarios|r")

	config.outdoorbox = CreateFrame("CheckButton", "AIoutdoorButton", config, "InterfaceOptionsCheckButtonTemplate")
	config.outdoorbox:SetPoint("TOPLEFT", config, 10, -168)
	config.outdoorbox:SetChecked(options.outdoors)
	config.outdoorboxtitle = config:CreateFontString("AIconfigoutdoorboxFont", "ARTWORK", "GameFontNormal")
	config.outdoorboxtitle:SetFont(GameFontNormal:GetFont(), 12, "OUTLINE")
	config.outdoorboxtitle:SetPoint("LEFT", config.outdoorbox, 30, 0)
	config.outdoorboxtitle:SetText("|cffffffffActive outdoors|r")

	config.channeltitle = config:CreateFontString("AIconfigchanneltitleFont", "ARTWORK", "GameFontNormal")
	config.channeltitle:SetFont(GameFontNormal:GetFont(), 12, "OUTLINE")
	config.channeltitle:SetPoint("TOPLEFT", config, 10, -208)
	config.channeltitle:SetText("|cffffffffChannel:|r")

	config.channeldropdown = CreateFrame("Button", "AIchannelDropdown", config, "UIDropDownMenuTemplate")
	config.channeldropdown:SetPoint("TOPLEFT", config, 10, -228)

	UIDropDownMenu_Initialize(config.channeldropdown, function(self, level)   
		local info = UIDropDownMenu_CreateInfo()
		local channelOptions = {
			"Say",
			"Raid",
			"Party",
			"Instance",
			"Yell",
			"Self",
			"Whisper",
			"Custom channel"
		}
		for k,v in pairs(channelOptions) do
			info = UIDropDownMenu_CreateInfo()
			info.text = v
			info.value = v
			info.func = function(self) UIDropDownMenu_SetSelectedID(config.channeldropdown, self:GetID()) if self:GetID() < 7 then config.channelextrabox:Hide() else config.channelextrabox:Show() end end
			UIDropDownMenu_AddButton(info, level)
		end 
	end)
	UIDropDownMenu_SetSelectedID(config.channeldropdown, selectIdFromChannelName(options.channel))

	config.channelextrabox = CreateFrame("EditBox", "AIextrachannelbox", config.channeldropdown, "InputBoxTemplate")
	config.channelextrabox:SetPoint("RIGHT", 250, 2)
	config.channelextrabox:SetSize(130, 25)
	config.channelextrabox:SetAutoFocus(false)
	config.channelextrabox:SetScript("OnEnterPressed", function(self) self:ClearFocus() end)
	if UIDropDownMenu_GetSelectedID(config.channeldropdown) < 7 then
		config.channelextrabox:Hide()
	end
	config.channelextrabox:SetText(options.channelExtra)

	config.outputtitle = config:CreateFontString("AIconfigoutputtitleFont", "ARTWORK", "GameFontNormal")
	config.outputtitle:SetFont(GameFontNormal:GetFont(), 12, "OUTLINE")
	config.outputtitle:SetPoint("TOPLEFT", config, 10, -268)
	config.outputtitle:SetText("|cffffffffOutput:|r")

	config.outputbox = CreateFrame("EditBox", "AIoutputbox", config, "InputBoxTemplate")
	config.outputbox:SetPoint("TOPLEFT", config, 20, -288)
	config.outputbox:SetSize(250, 25)
	config.outputbox:SetAutoFocus(false)
	config.outputbox:SetScript("OnEnterPressed", function(self) self:ClearFocus() end)
	config.outputbox:SetText(options.message)

	config.hints = config:CreateFontString("AIconfighintFont", "ARTWORK", "GameFontNormal")
	config.hints:SetFont(GameFontNormal:GetFont(), 10, "OUTLINE")
	config.hints:SetPoint("TOPLEFT", config, 12, -318)
	config.hints:SetText("|cffffffffHint:\n%t prints the target\n%sl prints a spell link of the interrupted spell\n%sn prints the name of the interrupted spell\n%sc prints the school of the interrupted spell\n%ys prints the spell that you used in order to interrupt|r")
	config.hints:SetJustifyH("LEFT")


	config:SetScript("OnShow", nil)
end


f:SetScript("OnEvent", function(self, event, ...)
    self[event](self, ...)
end)


function f:COMBAT_LOG_EVENT_UNFILTERED(...)
	local _, eventType, _, sourceGUID, _, _, _, _, destName, _, _, sourceID, _, _, spellID, spellName, spellSchool = ...
	if eventType == "SPELL_INTERRUPT" and sourceGUID == UnitGUID("player") then
		printFormattedString(destName, spellID, spellName, spellSchool, sourceID)
	end
end

function f:PLAYER_ENTERING_WORLD()
	registerEvents()
end

function f:ADDON_LOADED(addon)
    if addon ~= "AnnounceInterrupts" then return end

    local defaults = {
		channel = "SAY",
		channelExtra = "",
		enabled = true,
		inRaid = true,
		inParty = true,
		inBG = true,
		inArena = true,
		inScenario = true,
		outdoors = false,
		message = "Interrupted %sl on %t"
	}

	AnnounceInterruptsDB = AnnounceInterruptsDB or {}

	for k,v in pairs(defaults) do
		if AnnounceInterruptsDB[k] == nil then
			AnnounceInterruptsDB[k] = v
		end
	end

	options = AnnounceInterruptsDB

	

	config.name = "Announce Interrupts"
	config:SetScript("OnShow", showAIConfig)


	config.okay = function(self)
		AnnounceInterruptsDB.enabled = getBoolean(config.enablebox:GetChecked())
		AnnounceInterruptsDB.inRaid = getBoolean(config.raidbox:GetChecked())
		AnnounceInterruptsDB.inParty = getBoolean(config.partybox:GetChecked())
		AnnounceInterruptsDB.inArena = getBoolean(config.arenabox:GetChecked())
		AnnounceInterruptsDB.inScenario = getBoolean(config.scenariobox:GetChecked())
		AnnounceInterruptsDB.inBG = getBoolean(config.bgbox:GetChecked())
		AnnounceInterruptsDB.outdoors = getBoolean(config.outdoorbox:GetChecked())
		AnnounceInterruptsDB.message = config.outputbox:GetText()
		AnnounceInterruptsDB.channelExtra = config.channelextrabox:GetText()

		local channelOptions = {
			"SAY",
			"RAID",
			"PARTY",
			"INSTANCE_CHAT",
			"YELL",
			"SELF",
			"WHISPER",
			"CHANNEL"
		}
		AnnounceInterruptsDB.channel = channelOptions[UIDropDownMenu_GetSelectedID(config.channeldropdown)]

		options = AnnounceInterruptsDB
		registerEvents()
		
	end
	config.cancel = function(self)
		config.enablebox:SetChecked(options.enabled)
		config.raidbox:SetChecked(options.inRaid)
		config.partybox:SetChecked(options.inParty)
		config.bgbox:SetChecked(options.inBG)
		config.scenariobox:SetChecked(options.inScenario)
		config.arenabox:SetChecked(options.inArena)
		config.outdoorbox:SetChecked(options.outdoors)
		config.outputbox:SetText(options.message)
		config.channelextrabox:SetText(options.channelExtra)
		UIDropDownMenu_SetSelectedID(config.channeldropdown, selectIdFromChannelName(options.channel))
	end
	InterfaceOptions_AddCategory(config)




	SLASH_ANNOUNCEINTERRUPTS1, SLASH_ANNOUNCEINTERRUPTS2 = "/ai", "/announceinterrupts"
	SlashCmdList.ANNOUNCEINTERRUPTS = function(msg)
		InterfaceOptionsFrame_Show()
		InterfaceOptionsFrame_OpenToCategory(config)
		showAIConfig()
	end

	f:RegisterEvent("PLAYER_ENTERING_WORLD")
	registerEvents()
end

f:RegisterEvent("ADDON_LOADED")
